/**
 * All the functions needed to render objects effects
 *
 * Originally written by: Jonas Strandstedt
 */


/**
 * drawObjectExploding draws the object using direct rendering
 * @param GameObject *obj = the object to be rendered
 * @param GLfloat amount = the amount of explosion, 0.0 == no explosion, 1.0 == a lot of explosion
 * @param GLfloat boost = boost the explosion, static for the whole explosion
 *
 * This is a slow method of explosion rendering, but what to do?!
 */
void drawObjectExploding(PlayerObject *obj, GLfloat amount, GLfloat boost) {
	/*
	float directionArray[obj->mesh->iArraySize*3*3];
	int n=0;
	int m=0;
	while (m<obj->mesh->iArraySize) {
		// calculating the vector away from origo
		Vertex t = obj->mesh->varray[m];
		float length = sqrt(t.location[0]*t.location[0]+t.location[1]*t.location[1]+t.location[2]*t.location[2]);
		float dx = t.location[0] / length;
		float dy = t.location[1] / length;
		float dz = t.location[2] / length;
		directionArray[n] = dx;
		directionArray[n+1] = dy;
		directionArray[n+2] = dz;
		directionArray[n+3] = dx;
		directionArray[n+4] = dy;
		directionArray[n+5] = dz;
		directionArray[n+6] = dx;
		directionArray[n+7] = dy;
		directionArray[n+8] = dz;
		n+=9;
		m+=3;
	}
		
	
	float projectionModelviewMatrix[16];
	
	//Just set it to identity matrix
	memset(projectionModelviewMatrix, 0, sizeof(float)*16);
	projectionModelviewMatrix[0]=1.0;
	projectionModelviewMatrix[5]=1.0;
	projectionModelviewMatrix[10]=1.0;
	projectionModelviewMatrix[15]=1.0;
	
	//Bind the shader that we want to use
	glUseProgram(ShaderProgram[1]);
	//Setup all uniforms for your shader
	glUniformMatrix4fv(ProjectionModelviewMatrix_Loc[1], 1, 0, projectionModelviewMatrix);
	
	
	GLint myUniformLocation = glGetUniformLocation(ShaderProgram[1], "amount");
	glUniform1f(myUniformLocation, amount*boost);
	
	GLint location = glGetUniformLocation(ShaderProgram[1], "direction");
	glUniformMatrix3fv(location, 1, 0, directionArray);
	
	drawPlayerVBO(obj);
	
	
	glUseProgram(0);
	usleep(100000);
	*/
	
	if (obj->mesh->texture != 0) {
		glBindTexture(GL_TEXTURE_2D, obj->mesh->texture); 
	}
	int n=0;
	while (n<obj->mesh->iArraySize) {
		// saving current matrix to be able to revert later
		glPushMatrix();
		
		// calculating the vector away from origo
		Vertex t = obj->mesh->varray[n];
		float length = sqrt(t.location[0]*t.location[0]+t.location[1]*t.location[1]+t.location[2]*t.location[2]);
		float dx = t.location[0] / length;
		float dy = t.location[1] / length;
		float dz = t.location[2] / length;
			
		
		// translating away from origo and rotating around "itself"
		glTranslatef(dx*amount*boost,dy*amount*boost,dz*amount*boost);
		//glRotatef(amount*boost*2,dx,dy,dz);

		// drawing the triangle, aka 3 vertices
		glBegin(GL_TRIANGLES);
		int i = n;
		while (i < n+3) {
			Vertex tmp = obj->mesh->varray[i];
			glNormal3f(tmp.normal[0],tmp.normal[1],tmp.normal[2]);
			glColor4f(tmp.colour[0],tmp.colour[1],tmp.colour[2],tmp.colour[3]);
			glTexCoord2d(tmp.tex[0],tmp.tex[1]);
			glVertex3f(tmp.location[0],tmp.location[1],tmp.location[2]);
			i++;
		}
		n+=3;
		glEnd();
		
		// reverting to prepare for the next vertex
		glPopMatrix();
	}
	if (obj->mesh->texture != 0) {
		glBindTexture(GL_TEXTURE_2D, 0); 
	}
	 
	 
	int k = 0;
	while (k < (*obj).partsUsed) {
		glPushMatrix();
		StaticObject *temp = (obj->parts + k);
		float factor = amount*boost*4;
		if (((*temp).pos.x +(*temp).pos.y +(*temp).pos.z) == 0.0) {
			glTranslatef(0.0,0.0,factor);
		} else {
			glTranslatef((*temp).pos.x*factor, (*temp).pos.y*factor, (*temp).pos.z*factor);
		}

		drawMeshVBO(temp->mesh);
		glPopMatrix();
		k++;
	}
	 
}

/**
 * drawObjectExploding draws the object using direct rendering
 * @param GameObject *obj = the object to be rendered
 * @param GLfloat amount = the amount of explosion, 0.0 == no explosion, 1.0 == totally sunken!
 */
void drawObjectSinking(PlayerObject *obj, GLfloat amount) {
	float threshold = 0.3;
	if (amount>threshold) {
		glTranslatef(0.0f,0.0f,-(amount-threshold)*5);
	}
	glRotatef(-90*amount,0.0f,1.0f,0.0f);
	drawPlayerVBO(obj);

}

/**
 * drawObjectWhirlpool draws the object using direct rendering
 * @param GameObject *obj = the object to be rendered
 * @param GLfloat amount = time, 0->1
 */
void drawObjectWhirlpool(PlayerObject *obj, GLfloat amount, float boost, int time) {
	
	glPushMatrix();
	glRotatef(360*amount*boost,0.0f,0.0f,1.0f);
	
	float shrink = 0.3;
	float threshold = 0.8;
	
	if (time == 2) {
		glEnable(GL_BLEND);
		glBlendFunc(GL_ONE,GL_ONE);
	}
	
	if (amount < shrink) {
		drawPlayerVBO(obj);
	} else {
		if (amount > threshold) {
			glTranslatef(0.0f,0.0f,-(amount-threshold)*20);
		}
		int i=0;
		
		if (obj->mesh->texture != 0) {
			glBindTexture(GL_TEXTURE_2D, obj->mesh->texture); 
		}
		
		glBegin(GL_TRIANGLES);
		while (i<obj->mesh->iArraySize) {
			Vertex tmp = obj->mesh->varray[i];
			
			glNormal3f(tmp.normal[0],tmp.normal[1],tmp.normal[2]);
			glColor4f(tmp.colour[0],tmp.colour[1],tmp.colour[2],tmp.colour[3]);
			glTexCoord2d(tmp.tex[0],tmp.tex[1]);
			
			float factor = (1.0-(amount-shrink))*(1.0-(amount-shrink));
			glVertex3f(tmp.location[0]*factor,tmp.location[1]*factor,tmp.location[2]);
			i++;
		}
		glEnd();
		
		if (obj->mesh->texture != 0) {
			glBindTexture(GL_TEXTURE_2D, 0); 
		}
	}
	
	
	if (time == 2) {
		glDisable(GL_BLEND);
	}
	glPopMatrix();
	if (time == 1 && amount > shrink) {
		//drawObjectWhirlpool(obj, amount, boost/2, 2);
	} 
	
	
}

void renderCollisionObjectShader(CollisionObject *obj) {
	
	GLhandleARB currentShader = obj->shader;
	glUseProgramObjectARB(currentShader);
	
	if (obj->texture != -1) {
		glBindTexture( GL_TEXTURE_2D, textureArray[obj->texture] );
	}
	
	glPushMatrix();
	glTranslatef((*obj).pos.x, (*obj).pos.y, (*obj).pos.z);
	glRotatef((*obj).angle.x * 360 / M_PI / 2, 1.0f, 0, 0);
	glRotatef((*obj).angle.y * 360 / M_PI / 2, 0, 1.0f, 0);
	glRotatef((*obj).angle.z * 360 / M_PI / 2, 0, 0, 1.0f);
	
	float time = glfwGetTime();
	float projectionModelviewMatrix[16];
	memset(projectionModelviewMatrix, 0, sizeof(float)*16);
	projectionModelviewMatrix[0]=1.0;
	projectionModelviewMatrix[5]=1.0;
	projectionModelviewMatrix[10]=1.0;
	projectionModelviewMatrix[15]=1.0;
	
	//Bind the shader that we want to use
	//Setup all uniforms for your shader
	glUniformMatrix4fvARB(ProjectionModelviewMatrix_Loc[0], 1, 0, projectionModelviewMatrix);
	GLint myUniformLocation = glGetUniformLocationARB(currentShader, "time");
	glUniform1fARB(myUniformLocation, time);
	
	drawMeshVBO(modelArray[(*obj).model]);
	
	if (obj->texture != -1) {
		glBindTexture(GL_TEXTURE_2D, 0); 
	}
	
	glUseProgramObjectARB(0);
	
	glPopMatrix();
}